home *** CD-ROM | disk | FTP | other *** search
- /*
- * AFM library public interface.
- * Copyright (c) 1995 Markku Rossi.
- *
- * Author: Markku Rossi <mtr@iki.fi>
- */
-
- /*
- * This file is part of the AFM library.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #include "afmint.h"
- #include "afm.h"
-
- /*
- * Static variables
- */
-
- static char *default_path = "/usr/local/lib/ps:/usr/lib/ps";
-
- static char *error_names[] =
- {
- "AFM Success",
- "AFM Error",
- "out of memory",
- "illegal argument",
- "unknown font",
- "syntax error",
- "unsupported format",
- "file IO failed",
- "file is not an AFM file",
- };
-
- /*
- * Prototypes for static functions.
- */
-
- static void read_font_map __P ((AFMHandle handle, char *name));
- static void apply_encoding __P ((AFMFont font, AFMEncodingTable *enc,
- unsigned int flags));
-
-
- /*
- * Global functions.
- */
-
- void
- afm_error_to_string (AFMError error, char *buf)
- {
- char *syserr;
- int code, syserrno;
-
- code = error & 0xffff;
- syserrno = (error >> 16) & 0xffff;
-
- if (syserrno)
- syserr = strerror (syserrno);
- else
- syserr = NULL;
-
- if (code >= NUM_ERRORS)
- {
- sprintf (buf, "afm_error_to_string(): illegal error code: %d\n",
- error);
- return;
- }
-
- if (code == 0)
- sprintf (buf, "AFM Success");
- else if (code == 1)
- sprintf (buf, "%s%s%s", "AFM Error",
- syserr ? ":" : "",
- syserr ? syserr : "");
- else
- sprintf (buf, "AFM Error: %s%s%s", error_names[code],
- syserr ? ": " : "",
- syserr ? syserr : "");
- }
-
-
- AFMError
- afm_create (const char *path, unsigned int verbose_level,
- AFMHandle *handle_return)
- {
- AFMHandle handle;
- AFMError error = AFM_SUCCESS;
- const char *cp, *cp2;
- int len;
- char buf[512];
- struct stat stat_st;
-
- /* Init handle. */
-
- handle = (AFMHandle) calloc (1, sizeof (*handle));
- if (handle == NULL)
- {
- error = AFM_ERROR_MEMORY;
- goto error_out;
- }
-
- handle->font_map = strhash_init ();
- if (handle->font_map == NULL)
- {
- error = AFM_ERROR_MEMORY;
- goto error_out;
- }
-
- handle->verbose = verbose_level;
-
- /* Traverse path. */
-
- if (path == NULL)
- path = default_path;
-
- afm_message (handle, 1, "AFM: scanning path...\n");
- for (cp = path; cp; cp = strchr (cp, PATH_SEPARATOR))
- {
- if (cp != path)
- cp++;
-
- cp2 = strchr (cp, PATH_SEPARATOR);
- if (cp2)
- len = cp2 - cp;
- else
- len = strlen (cp);
-
- memcpy (buf, cp, len);
- buf[len] = '\0';
- if (len > 0 && buf[len - 1] == '/')
- buf[len - 1] = '\0';
-
- strcat (buf, "/font.map");
-
- if (stat (buf, &stat_st) == 0)
- read_font_map (handle, buf);
- }
-
- *handle_return = handle;
-
- return AFM_SUCCESS;
-
-
- /* Error handling. */
-
- error_out:
-
- (void) afm_destroy (handle);
-
- return error;
- }
-
-
- AFMError
- afm_destroy (AFMHandle handle)
- {
- char *key;
- int keylen;
- char *cp;
-
- if (handle == NULL)
- return AFM_ERROR_ARGUMENT;
-
- /* Free filenames. */
- while (strhash_get_first (handle->font_map, &key, &keylen, (void *) &cp))
- free (cp);
-
- strhash_free (handle->font_map);
- free (handle);
-
- return AFM_SUCCESS;
- }
-
-
- AFMError
- afm_set_verbose (AFMHandle handle, unsigned int level)
- {
- if (handle == NULL)
- return AFM_ERROR_ARGUMENT;
-
- handle->verbose = level;
-
- return AFM_SUCCESS;
- }
-
-
- AFMError
- afm_font_prefix (AFMHandle handle, const char *fontname,
- const char **prefix_return)
- {
- char *filename;
-
- if (handle == NULL || fontname == NULL || prefix_return == NULL)
- return AFM_ERROR_ARGUMENT;
-
- /* Lookup font. */
- if (!strhash_get (handle->font_map, fontname, strlen (fontname),
- (void *) &filename))
- return AFM_ERROR_UNKNOWN_FONT;
-
- *prefix_return = filename;
-
- return AFM_SUCCESS;
- }
-
-
- AFMError
- afm_open_font (AFMHandle handle, unsigned int info_level,
- const char *fontname, AFMFont *font_return)
- {
- char *filename;
- char fname[512];
-
- if (handle == NULL || fontname == NULL)
- return AFM_ERROR_ARGUMENT;
-
- /* Lookup font. */
- if (!strhash_get (handle->font_map, fontname, strlen (fontname),
- (void *) &filename))
- return AFM_ERROR_UNKNOWN_FONT;
-
- /* Append suffix to the filename. */
- sprintf (fname, "%s.afm", filename);
-
- return afm_open_file (handle, info_level, fname, font_return);
- }
-
-
- AFMError
- afm_open_file (AFMHandle handle, unsigned int info_level,
- const char *filename, AFMFont *font_return)
- {
- AFMFont font;
- AFMError error = AFM_SUCCESS;
-
- if (handle == NULL || filename == NULL)
- return AFM_ERROR_ARGUMENT;
-
- font = (AFMFont) calloc (1, sizeof (*font));
- if (font == NULL)
- return AFM_ERROR_MEMORY;
-
- font->private
- = (struct afm_font_private_data_st *) calloc (1, sizeof (*font->private));
- if (font->private == NULL)
- {
- error = AFM_ERROR_MEMORY;
- goto error_out;
- }
- font->private->fontnames = strhash_init ();
- if (font->private->fontnames == NULL)
- {
- error = AFM_ERROR_MEMORY;
- goto error_out;
- }
-
- font->private->compositenames = strhash_init ();
- if (font->private->compositenames == NULL)
- {
- error = AFM_ERROR_MEMORY;
- goto error_out;
- }
-
- font->info_level = info_level;
-
- /* Parse file. */
- if (setjmp (handle->jmpbuf))
- {
- /* Error during parse. */
- error = handle->parse_error;
- goto error_out;
- }
- else
- {
- afm_parse_file (handle, filename, font);
- /* Parse successful. */
- }
-
- *font_return = font;
- return AFM_SUCCESS;
-
-
- /* Error handling. */
-
- error_out:
-
- (void) afm_close_font (font);
-
- return error;
- }
-
-
- #define FREE(ptr) if (ptr) free (ptr)
- AFMError
- afm_close_font (AFMFont font)
- {
- int i;
-
- if (font == NULL)
- return AFM_ERROR_ARGUMENT;
-
- /* Global info. */
- FREE (font->global_info.FontName);
- FREE (font->global_info.FullName);
- FREE (font->global_info.FamilyName);
- FREE (font->global_info.Weight);
- FREE (font->global_info.Version);
- FREE (font->global_info.Notice);
- FREE (font->global_info.EncodingScheme);
- FREE (font->global_info.CharacterSet);
-
- /* Character metrics. */
- for (i = 0; i < font->num_character_metrics; i++)
- FREE (font->character_metrics[i].name);
- FREE (font->character_metrics);
-
- /* Composites. */
- for (i = 0; i < font->num_composites; i++)
- FREE (font->composites[i].name);
- FREE (font->composites);
-
- /* Kern pairs. */
- for (i = 0; i < font->num_kern_pairs; i++)
- {
- FREE (font->kern_pairs[i].name1);
- FREE (font->kern_pairs[i].name2);
- }
- FREE (font->kern_pairs);
-
- /* Track kern. */
- FREE (font->track_kerns);
-
- /* Private data. */
- strhash_free (font->private->fontnames);
- strhash_free (font->private->compositenames);
-
- free (font);
-
- return AFM_SUCCESS;
- }
-
-
- #define STR(str) (str ? str : "")
- #define BOOL(val) (val ? "true" : "false")
- void
- afm_font_dump (FILE *fp, AFMFont font)
- {
- int i;
-
- fprintf (fp, "AFM Format Specification version: %g\n", font->version);
- fprintf (fp, "Global Font Information\n");
- fprintf (fp, " FontName:\t%s\n", STR (font->global_info.FontName));
- fprintf (fp, " FullName:\t%s\n", STR (font->global_info.FullName));
- fprintf (fp, " FamilyName:\t%s\n", STR (font->global_info.FamilyName));
- fprintf (fp, " Weight:\t%s\n", STR (font->global_info.Weight));
- fprintf (fp, " FontBBox:\t%g %g %g %g\n",
- font->global_info.FontBBox_llx, font->global_info.FontBBox_lly,
- font->global_info.FontBBox_urx, font->global_info.FontBBox_ury);
- fprintf (fp, " Version:\t%s\n", STR (font->global_info.Version));
- fprintf (fp, " Notice:\t%s\n", STR (font->global_info.Notice));
- fprintf (fp, " EncodingScheme:\t%s\n",
- STR (font->global_info.EncodingScheme));
- fprintf (fp, " MappingScheme:\t%ld\n", font->global_info.MappingScheme);
- fprintf (fp, " EscChar:\t%ld\n", font->global_info.EscChar);
- fprintf (fp, " CharacterSet:\t%s\n", STR (font->global_info.CharacterSet));
- fprintf (fp, " Characters:\t%ld\n", font->global_info.Characters);
- fprintf (fp, " IsBaseFont:\t%s\n", BOOL(font->global_info.IsBaseFont));
- fprintf (fp, " VVector:\t%g %g\n",
- font->global_info.VVector_0, font->global_info.VVector_1);
- fprintf (fp, " IsFixedV:\t%s\n", BOOL(font->global_info.IsFixedV));
- fprintf (fp, " CapHeight:\t%g\n", font->global_info.CapHeight);
- fprintf (fp, " XHeight:\t%g\n", font->global_info.XHeight);
- fprintf (fp, " Ascender:\t%g\n", font->global_info.Ascender);
- fprintf (fp, " Descender:\t%g\n", font->global_info.Descender);
-
- for (i = 0; i < 2; i++)
- if (font->writing_direction_metrics[i].is_valid)
- {
- fprintf (fp, "Writing Direction %d\n", i);
- fprintf (fp, " UnderlinePosition: %g\n",
- font->writing_direction_metrics[i].UnderlinePosition);
- fprintf (fp, " UnderlineThickness: %g\n",
- font->writing_direction_metrics[i].UnderlineThickness);
- fprintf (fp, " ItalicAngle: %g\n",
- font->writing_direction_metrics[i].ItalicAngle);
- fprintf (fp, " CharWidth: %g %g\n",
- font->writing_direction_metrics[i].CharWidth_x,
- font->writing_direction_metrics[i].CharWidth_y);
- fprintf (fp, " IsFixedPitch: %s\n",
- BOOL (font->writing_direction_metrics[i].IsFixedPitch));
- }
-
- /* Individual Character Metrics. */
- fprintf (fp, "Individual Character Metrics %ld\n",
- font->num_character_metrics);
- for (i = 0; i < font->num_character_metrics; i++)
- {
- AFMIndividualCharacterMetrics *cm;
- cm = &font->character_metrics[i];
-
- fprintf (fp, " C %ld ; N %s ; B %g %g %g %g\n",
- cm->character_code, STR (cm->name),
- cm->llx, cm->lly, cm->urx, cm->ury);
- fprintf (fp,
- " W0X %g ; W0Y %g ; W1X %g ; W1Y %g ; VV %g %g\n",
- cm->w0x, cm->w0y, cm->w1x, cm->w1y, cm->vv_x, cm->vv_y);
- }
-
- /* Composite Character Data. */
- fprintf (fp, "Composite Character Data %ld\n", font->num_composites);
- for (i = 0; i < font->num_composites; i++)
- {
- AFMComposite *cm;
- int j;
-
- cm = &font->composites[i];
-
- fprintf (fp, " CC %s %ld", cm->name, cm->num_components);
- for (j = 0; j < cm->num_components; j++)
- fprintf (fp, " ; PCC %s %g %g",
- cm->components[j].name,
- cm->components[j].deltax,
- cm->components[j].deltay);
- fprintf (fp, "\n");
- }
-
- /* Kern pairs. */
- fprintf (fp, "Pair-Wise Kerning %ld\n", font->num_kern_pairs);
- for (i = 0; i < font->num_kern_pairs; i++)
- {
- AFMPairWiseKerning *kp;
- kp = &font->kern_pairs[i];
-
- fprintf (fp, " KP %s %s %g %g\n", STR (kp->name1), STR (kp->name2),
- kp->kx, kp->ky);
- }
-
- fprintf (fp, "Track Kerning %ld\n", font->num_track_kerns);
- for (i = 0; i < font->num_track_kerns; i++)
- {
- AFMTrackKern *tk;
- tk = &font->track_kerns[i];
-
- fprintf (fp, " TrackKern %ld %g %g %g %g\n", tk->degree,
- tk->min_ptsize, tk->min_kern,
- tk->max_ptsize, tk->max_kern);
- }
- }
-
-
- AFMError
- afm_font_stringwidth (AFMFont font, AFMNumber ptsize, char *string,
- unsigned int stringlen, AFMNumber *w0x_return,
- AFMNumber *w0y_return)
- {
- unsigned int i;
- AFMNumber x = 0.0;
- AFMNumber y = 0.0;
- AFMIndividualCharacterMetrics *cm;
-
- if (!font || !string || !font->writing_direction_metrics[0].is_valid)
- return AFM_ERROR_ARGUMENT;
-
- /* Check shortcut. */
- if (font->writing_direction_metrics[0].IsFixedPitch)
- {
- /* This is the easy case. */
- x = stringlen * font->writing_direction_metrics[0].CharWidth_x;
- y = stringlen * font->writing_direction_metrics[0].CharWidth_y;
- }
- else
- {
- /* Count character by character. */
- for (i = 0; i < stringlen; i++)
- {
- cm = font->encoding[(unsigned int) string[i]];
- if (cm == AFM_ENC_NONE || cm == AFM_ENC_NON_EXISTENT)
- {
- /* Use the undef font. */
- x += font->private->undef->w0x;
- y += font->private->undef->w0y;
- }
- else
- {
- /* Font found and valid, take values. */
- x += cm->w0x;
- y += cm->w0y;
- }
- }
- }
-
- *w0x_return = x / UNITS_PER_POINT * ptsize;
- *w0y_return = y / UNITS_PER_POINT * ptsize;
-
- return AFM_SUCCESS;
- }
-
-
- AFMError
- afm_font_charwidth (AFMFont font, AFMNumber ptsize, unsigned int ch,
- AFMNumber *w0x_return, AFMNumber *w0y_return)
- {
- AFMNumber x = 0.0;
- AFMNumber y = 0.0;
- AFMIndividualCharacterMetrics *cm;
-
- if (!font || !font->writing_direction_metrics[0].is_valid)
- return AFM_ERROR_ARGUMENT;
-
- /* Check shortcut. */
- if (font->writing_direction_metrics[0].IsFixedPitch)
- {
- x = font->writing_direction_metrics[0].CharWidth_x;
- y = font->writing_direction_metrics[0].CharWidth_y;
- }
- else
- {
- cm = font->encoding[(unsigned int) ch];
- if (cm == AFM_ENC_NONE || cm == AFM_ENC_NON_EXISTENT)
- {
- /* Use the undef font. */
- x = font->private->undef->w0x;
- y = font->private->undef->w0y;
- }
- else
- {
- /* Font found and valid, take values. */
- x = cm->w0x;
- y = cm->w0y;
- }
- }
-
- *w0x_return = x / UNITS_PER_POINT * ptsize;
- *w0y_return = y / UNITS_PER_POINT * ptsize;
-
- return AFM_SUCCESS;
- }
-
-
- AFMError
- afm_font_encode (AFMFont font, unsigned char code, char *name,
- unsigned int flags)
- {
- AFMIndividualCharacterMetrics *cm;
- AFMComposite *comp;
-
- if (font == NULL)
- return AFM_ERROR_ARGUMENT;
-
- if (name)
- {
- /* Get font. */
- if (!strhash_get (font->private->fontnames, name, strlen (name),
- (void *) &cm))
- {
- /* Check composite characters. */
- if ((flags & AFM_ENCODE_ACCEPT_COMPOSITES) == 0
- || strhash_get (font->private->compositenames, name,
- strlen (name), (void *) &comp) == 0)
- cm = AFM_ENC_NON_EXISTENT;
- else
- {
- /*
- * Ok, composite character found, now find the character
- * specified by the first composite component.
- */
- if (!strhash_get (font->private->fontnames,
- comp->components[0].name,
- strlen (comp->components[0].name),
- (void *) &cm))
- cm = AFM_ENC_NON_EXISTENT;
- }
- }
- }
- else
- cm = AFM_ENC_NONE;
-
- font->encoding[(unsigned int) code] = cm;
-
- return AFM_SUCCESS;
- }
-
-
- AFMError
- afm_font_encoding (AFMFont font, AFMEncoding enc, unsigned int flags)
- {
- int i;
- AFMIndividualCharacterMetrics *cm;
-
- if (font == NULL)
- return AFM_ERROR_ARGUMENT;
-
- switch (enc)
- {
- case AFM_ENCODING_DEFAULT:
- /* Clear encoding. */
- for (i = 0; i < 256; i++)
- font->encoding[i] = AFM_ENC_NONE;
-
- /* Apply font's default encoding. */
- for (i = 0; i < font->num_character_metrics; i++)
- {
- cm = &font->character_metrics[i];
- font->encoding[cm->character_code] = cm;
- }
- break;
-
- case AFM_ENCODING_LATIN1:
- apply_encoding (font, afm_latin1_encoding, flags);
- break;
-
- case AFM_ENCODING_LATIN2:
- apply_encoding (font, afm_latin2_encoding, flags);
- break;
-
- case AFM_ENCODING_LATIN3:
- apply_encoding (font, afm_latin3_encoding, flags);
- break;
-
- case AFM_ENCODING_IBMPC:
- apply_encoding (font, afm_ibmpc_encoding, flags);
- break;
-
- case AFM_ENCODING_ASCII:
- /*
- * First apply one encoding (all have equal first 128 characters),
- * then zap last 128 chars.
- */
- apply_encoding (font, afm_latin1_encoding, flags);
- for (i = 128; i < 256; i++)
- font->encoding[i] = AFM_ENC_NONE;
- break;
-
- case AFM_ENCODING_MAC:
- apply_encoding (font, afm_mac_encoding, flags);
- break;
-
- case AFM_ENCODING_VMS:
- apply_encoding (font, afm_vms_encoding, flags);
- break;
-
- case AFM_ENCODING_HP8:
- apply_encoding (font, afm_hp8_encoding, flags);
- break;
- }
-
- return AFM_SUCCESS;
- }
-
-
- /*
- * Internal help functions.
- */
-
-
- void
- #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
- afm_message (AFMHandle handle, int level, char *fmt, ...)
- #else
- afm_message (handle, level, va_alist)
- AFMHandle handle;
- int level;
- va_dcl
- #endif
- {
- va_list args;
- #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
- va_start(args, fmt);
- #else
- char *fmt;
-
- va_start(args);
- fmt = va_arg(args, char *);
- #endif
-
- if (handle->verbose < level)
- return;
-
- #ifdef HAVE_VPRINTF
- vfprintf (stderr, fmt, args);
- #else
- _doprnt(fmt, args, stderr);
- #endif
- va_end (args);
- }
-
-
- void
- #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
- afm_error (AFMHandle handle, char *fmt, ...)
- #else
- afm_error (handle, va_alist)
- AFMHandle handle;
- va_dcl
- #endif
- {
- va_list args;
- #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
- va_start(args, fmt);
- #else
- char *fmt;
-
- va_start(args);
- fmt = va_arg(args, char *);
- #endif
-
- fprintf (stderr, "AFM Error: ");
-
- #ifdef HAVE_VPRINTF
- vfprintf (stderr, fmt, args);
- #else
- _doprnt(fmt, args, stderr);
- #endif
-
- va_end (args);
- fprintf (stderr, "\n");
- }
-
-
- /*
- * Static functions.
- */
-
- static void
- read_font_map (AFMHandle handle, char *name)
- {
- FILE *fp;
- char buf[512];
- char fullname[512];
- unsigned int dirlen;
- char *cp, *cp2;
-
- afm_message (handle, 1, "AFM: reading font map \"%s\"\n", name);
-
- fp = fopen (name, "r");
- if (fp == NULL)
- {
- afm_message (handle, 1, "AFM: couldn't open font map \"%s\": %s\n",
- name, strerror (errno));
- return;
- }
-
- /* Get directory */
- cp = strrchr (name, '/');
- if (cp)
- {
- dirlen = cp - name + 1;
- memcpy (fullname, name, dirlen);
- }
- else
- {
- dirlen = 2;
- memcpy (fullname, "./", dirlen);
- }
-
- while (fgets (buf, sizeof (buf), fp))
- {
- char font[256];
- char file[256];
-
- if (sscanf (buf, "%s %s", font, file) != 2)
- {
- afm_error (handle, "malformed line in font map \"%s\":\n%s",
- name, buf);
- continue;
- }
-
- /* Do we already have this font? */
- if (strhash_get (handle->font_map, font, strlen (font), (void *) &cp))
- continue;
-
- /* Append file name. */
- strcpy (fullname + dirlen, file);
- cp = (char *) malloc (strlen (fullname) + 1);
- if (cp == NULL)
- {
- afm_error (handle, "couldn't add font: out of memory");
- goto out;
- }
- strcpy (cp, fullname);
-
- afm_message (handle, 2, "AFM: font mapping: %s -> %s\n", font, cp);
- (void) strhash_put (handle->font_map, font, strlen (font), cp,
- (void *) &cp2);
- }
-
- out:
- fclose (fp);
- }
-
-
- static void
- apply_encoding (AFMFont font, AFMEncodingTable *enc, unsigned int flags)
- {
- int i;
- AFMIndividualCharacterMetrics *cm;
- AFMComposite *comp;
-
- for (i = 0; enc[i].code >= 0; i++)
- {
- if (enc[i].character == AFM_ENC_NONE)
- font->encoding[enc[i].code] = AFM_ENC_NONE;
- else if (enc[i].character == AFM_ENC_NON_EXISTENT)
- font->encoding[enc[i].code] = AFM_ENC_NON_EXISTENT;
- else
- {
- if (strhash_get (font->private->fontnames, enc[i].character,
- strlen (enc[i].character), (void *) &cm))
- font->encoding[enc[i].code] = cm;
- else
- {
- /* Check composite characters. */
- if ((flags & AFM_ENCODE_ACCEPT_COMPOSITES) == 0
- || strhash_get (font->private->compositenames,
- enc[i].character, strlen (enc[i].character),
- (void *) &comp) == 0)
- font->encoding[enc[i].code] = AFM_ENC_NON_EXISTENT;
- else
- {
- /* Composite character found. */
- if (strhash_get (font->private->fontnames,
- comp->components[0].name,
- strlen (comp->components[0].name),
- (void *) &cm))
- font->encoding[enc[i].code] = cm;
- else
- font->encoding[enc[i].code] = AFM_ENC_NON_EXISTENT;
- }
- }
- }
- }
- }
-